﻿using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace TD.Interface
{
    /// <summary>
    /// The type of cursor to change to.
    /// </summary>
    public enum CursorType
    {
        /// <summary>
        /// Do not draw the cursor.
        /// </summary>
        None,

        /// <summary>
        /// The arrow has its origin on the top-left corner of the texture.
        /// </summary>
        Arrow,

        /// <summary>
        /// The crosshair has its origin in the middle-center of the texture.
        /// </summary>
        Crosshair
    }

    public class Cursor : DrawableGameComponent
    {
        private static Texture2D _cursor;
        private static CursorType _type;
        private static Vector2 _origin;
        private static Game1 _game;
        private static String _asset;

        private SpriteBatch spriteBatch;
        private Rectangle destRect;

        public Cursor(Game1 game) :
            base(game)
        {
            // The cursor is always top-most.
            base.DrawOrder = 0x0FFFFFFF;

            // To manipulate the cursor texture.
            _game = game;

            // Set the type of the cursor.
            _type = CursorType.Arrow;

            // Load no asset by default.
            _asset = string.Empty;
        }

        public override void Initialize()
        {
            // Ensure there are values for the cursor.
            destRect = new Rectangle(0, 0, 0, 0);
            _origin = new Vector2(0, 0);

            base.Initialize();
        }

        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(base.GraphicsDevice);

            // Load the default cursor.
            ChangeToDefault();
            
            base.LoadContent();
        }

        public override void Update(GameTime gameTime)
        {
            // Now update the position of the cursor.
            Point point = ((Game1)Game).InputManager.GetMouseLocation();
            destRect = new Rectangle(point.X, point.Y, _cursor.Bounds.Width, _cursor.Bounds.Height);
            
            base.Update(gameTime);
        }

        public override void Draw(GameTime gameTime)
        {
            // First validate we have to draw the cursor.
            if (_type != CursorType.None)
            {
                // Draw the cursor.
                spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.NonPremultiplied);
                spriteBatch.Draw(_cursor, destRect, _cursor.Bounds, Color.White, 0.0f, _origin, SpriteEffects.None, 0.0f);
                spriteBatch.End();
            }

            base.Draw(gameTime);
        }

        /// <summary>
        /// Hide the cursor. (Use Change to show it again!)
        /// </summary>
        public static void Hide()
        {
            _type = CursorType.None;
        }

        /// <summary>
        /// Change the cursor to the default cursor.
        /// </summary>
        public static void ChangeToDefault()
        {
            Change("interface\\cursor\\cursor_arrow", CursorType.Arrow);
        }

        /// <summary>
        /// Change the texture of the cursor.
        /// </summary>
        /// <param name="assetName">The asset name of the new cursor texture.</param>
        /// <param name="type">The type determines the origin of the cursor.</param>
        public static void Change(string assetName, CursorType type)
        {
            if (_asset != assetName)
            {
                // Assign the assetname to be the current asset used.
                _asset = assetName;

                // Load and assign the texture to the cursor.
                _game.TextureManager.LoadAsset(assetName);
                _cursor = _game.TextureManager.UseAsset(assetName);

                // And finally set the origin. (Click point on the texture.)
                if (type == CursorType.Arrow)
                {
                    _origin = new Vector2(0, 0);
                }
                else
                {
                    _origin = new Vector2((_cursor.Width >> 0x01), (_cursor.Height >> 0x01));
                }

                // Ensure we save the type.
                _type = type;
            }
        }
    }
}
